package eclipse.lib.map;

import javax.media.opengl.*;
import javax.media.opengl.jgloo.*;
import javax.media.opengl.jgloo.jgl2d.*;
import javax.media.opengl.jgloo.jglsh.*;

import eclipse.client.Database;
/*
 * Copyright (c) 2009, TOD Productions All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *	- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *	- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 *	-Neither the name of the organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
public final class Map implements JGLRenderable
{
	//Name of the map
	private String 			name;
	//Background music or Stream
	private String 			music;
	//Morality of the Map (laws)
	private MapMorality 	morality;
	//Determines if the light is rendered, max = 8
	private final boolean 		lightEnabled[] = new boolean[8];
	//Determines the color of the light, max = 8
	private final JGLColor		lightColor[] = new JGLColor[8];
	//Determines where a player respawns when they die
	private Respawn 		respawn;
	//The number of the map file
	private int 			mapIndex;
	//The maps associated North, South, East, and West of this map
	private Linking 		linkedMaps;
	//The number of layers in the map
	private int 			layerCount;
	//The layer objects
	private Layer[]			layer;
	//The Title of the map, displayed at the top
	private JGLText			title;
	
	/**
	 * Builds a Map object based off of its name and the number of layers it has.
	 * @param name
	 * @param layerCount
	 */
	public Map(String name, int layerCount)
	{
		//set the default linked map
		this.linkedMaps = new Linking(0, 0, 0, 0);
		//set the default respawn point
		this.respawn = new Respawn(0, 0, 0, 0);
		//set the default morality
		this.morality = MapMorality.NONE;
				
		//Sets the name of the map
		this.name 			= name;
		
		setLayerCount(layerCount);
		//Scrolls through the array of lights and creates the Objects
		for(int i = 0; i < 8; i++)
		{
			//Builds each individual light Object
			lightColor[i] = new JGLColor(1f, 1f, 1f);
		}
		//Builds the OpenGL Object for displaying the Tile of the map
		title = new JGLText(name);
		//Sets the font texture of the OpenGL Object
		title.setText(Database.tFont);
		//Offsets the font to approximately the middle
		//TODO: change this to offset to the exact middle
		title.setOffset(300, 10);
		
	}
	/**
	 * Similar to the render methods of GLObjects
	 * This will render each layer which then renders each tile
	 * @param gl Opengl Instance
	 */
	public final void render(GL gl)
	{
		//Scroll through each layer
		for(int i = 0; i < layer.length; i++)
		{
			//Check to confirm the layer exists just in case
			if(layer[i] != null)
			{
				//Only render if the layer is visible
				if(layer[i].isVisible())
				{
					//draw the layer
					layer[i].render(gl);
				}
			}		
		}		
		//Draw the caption that displays the name of the map
		title.render(gl);
	}
	/**
	 * Sets the String-path associated with the location of the Music's stream
	 * @param music String-path in the format of an ERL
	 */
	public final void setMusic(String music) {
		//Overwrite the previous String-path
		this.music = music;
	}
	/**
	 * Returns the String-path for the music's stream
	 * @return String-path that points to the music's stream
	 */
	public final String getMusic() {
		//Returns the String-path associated with the Music for this map
		return music;
	}
	/**
	 * Overwrites the current name of the map
	 * @param name Name to be displayed by the Name-Caption for this map
	 */
	public final void setName(String name) 
	{
		try
		{
			//update the caption with the new Name value
			title.setCaption(name);
		}
		catch(Exception e)
		{
			//dump any errors that might have occurred
			//ErrorManager.handleError(e);
		}		
		//update the name value with the new name
		this.name = name;
		
	}
	/**
	 * Returns the name value for the map
	 * @return Name that the map is associated with
	 */
	public final String getName() 
	{
		//Returns the name of the map, this is what is drawn by the Title caption
		return name;
	}
	/**
	 * Sets the morality of the map
	 * @param morality The Morality to set the map. Can use MapMorality.getMorality(byte)
	 */
	public final void setMorality(MapMorality morality)
	{
		//Overwrites the pointer of this maps morality with a new one
		this.morality = morality;
	}
	/**
	 * Returns the morality of the map
	 * @return Morality object that defines the rules of the map
	 */
	public final MapMorality getMorality() 
	{
		//Returns the pointer of this maps morality
		return morality;
	}
	/** 
	 * Enables/Disables lighting
	 * @param index Light to modify
	 * @param light True = Light on, False = Light off
	 */
	public final void setLightEnabled(int index, boolean light) 
	{
		//Toggles the state of the light
		this.lightEnabled[index] = light;
	}
	/**
	 * Returns whether a light is on
	 * @param index Light to check
	 * @return True = light is on, false = light is off
	 */
	public final boolean isLightEnabled(int index)
	{
		//returns a boolean that represents whether or not the light is on
		return lightEnabled[index];
	}
	/**
	 * Overwrites the previously set color that defines the lighting for the map
	 * @param index Light to modify the color of
	 * @param color Color to modify the light
	 */
	public final void setLightColor(int index, JGLColor color) 
	{
		//Overwrites the color field for the light
		this.lightColor[index] = color;
	}
	/**
	 * Obtains the color of the specified light
	 * @param index Light of which the color is obtained from
	 * @return
	 */
	public final JGLColor getLightColor(int index)
	{
		//returns the color that defines the light
		return this.lightColor[index];
	}
	/**
	 * Overwrites the current spawn point for the map.
	 * @param map Map the player respawns at when he/she dies
	 * @param x X-point which the player respawns at
	 * @param y Y-point which the player respawns at
	 * @param height Layer which the player respawns at
	 */
	public final void setRespawn(int map, int x, int y, int height)
	{
		//update the respawn point by creating a new respawn object in place of the old one
		this.respawn = new Respawn(map, x, y, height);
	}
	/**
	 * Overwrites the current spawn point for the map by replacing it with another
	 * @param respawn Respawn object to replace the 
	 */
	public final void setRespawn(Respawn respawn)
	{
		//
		this.respawn = respawn;
	}
	/**
	 * Obtains the respawn point of the map
	 * @return Respawn object
	 */
	public final Respawn getRespawn()
	{
		return respawn;
	}
	public final void setLayerCount(int layerCount) 
	{
		this.layerCount = layerCount;
		//Updates the array of layers for the map
		layer = new Layer[layerCount];
		//Scrolls through the array of layers and creates the Objects
		for(int i = 0; i < layerCount; i++)
		{
			//Builds each individual layer Object
			layer[i] = new Layer(20, 15);
		}
		
	}
	public final int getLayerCount() {
		return layerCount;
	}
	public final void setLinkedMaps(int north, int south, int east, int west)
	{
		this.linkedMaps = new Linking(north, south, east, west);
	}
	public final void setLinkedMaps(Linking linkedMaps) {
		this.linkedMaps = linkedMaps;
	}
	public final Linking getLinkedMaps() {
		return linkedMaps;
	}
	public final void setMapIndex(int mapIndex) {
		this.mapIndex = mapIndex;
	}
	public final int getMapIndex() {
		return mapIndex;
	}
	public final void setLayer(int index, Layer layer) {
		this.layer[index] = layer;
	}
	public final Layer getLayer(int index) {
		return layer[index];
	}
	public final class Respawn
	{
		public Respawn(int map, int x, int y, int height)
		{
			this.map	= map;
			this.x 		= x;
			this.y 		= y;
			this.height = height;
		}
		public int map;
		public int x;
		public int y;
		public int height;
	}
	public final class Linking
	{
		public Linking(int north, int south, int east, int west)
		{
			this.north 	= north;
			this.south 	= south;
			this.east	= east; 
			this.west 	= west;
		}
		public int north;
		public int south;
		public int east;
		public int west;
	}
}
